package com.db.utils;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.db.query.Range;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.reflect.FieldUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author dzh
 * @since 2024/12/30
 */
public class QueryMybatisPlusUtils {

    public static <T> QueryWrapper<T> queryWrapper(Object param, Class<T> entityType) {
        Field[] fields = FieldUtils.getAllFields(param.getClass());
        QueryWrapper<T> qr = Wrappers.query();
        try {
            for (Field field : fields) {
                field.setAccessible(true);
                String name = toColumnName(field.getName(), entityType);
                Class<?> type = field.getType();
                Object value = field.get(param);
                if (ObjectUtil.isNotEmpty(value)) {
                    if (value instanceof Range) {
                        Range<?> range = (Range<?>) value;
                        if (ObjectUtils.allNotNull(range.getMinimum(), range.getMaximum())) {
                            qr.between(name, range.getMinimum(), range.getMaximum());
                        } else if (range.getMinimum() != null) {
                            qr.ge(name, range.getMinimum());
                        } else if (range.getMaximum() != null) {
                            qr.le(name, range.getMaximum());
                        }
                    } else if (type.isPrimitive()) {
                        qr.eq(name, value);
                    } else if (value instanceof Collection) {
                        Collection<?> collection = (Collection<?>) value;
                        qr.in(name, collection);
                    } else if (value.getClass().isArray()) {
                        Collection<?> collection = Arrays.stream(((Object[]) value)).collect(Collectors.toList());
                        qr.in(name, collection);
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return qr;
    }

    public static String toColumnName(String name, Class<?> type) {
        TableInfo tableInfo = TableInfoHelper.getTableInfo(type);
        if (tableInfo.getKeyProperty().equals(name)) {
            return tableInfo.getKeyColumn();
        }
        List<TableFieldInfo> fieldList = tableInfo.getFieldList();
        return fieldList.stream()
                .filter(item -> item.getField().getName().equals(name))
                .findAny()
                .map(TableFieldInfo::getColumn)
                .orElseThrow(() -> new RuntimeException("字段不存在：" + name));
    }
}
